
#ifndef _BINARY_TREE_
#define _BINARY_TREE_

#include "Common/Math.h"

template <class T>
struct BinaryTree
{
	private:
		BinaryTree *left;
		BinaryTree *right;
		size_t child_count;
		T value;
	public:
		inline BinaryTree(T value)
		{
			this->value = value;
			this->left = NULL;
			this->right = NULL;
			this->child_count = 0;
		}
		inline void attachLeft(BinaryTree<T> *left)
		{
			if (this->left != NULL)
			{
				child_count -= this->left->child_count + 1;
				delete this->left;
			}
			this->left = left;
			if (left != NULL)
				child_count += left->child_count + 1;
		}
		inline void attachRight(BinaryTree<T> *right)
		{
			if (this->right != NULL)
			{
				child_count -= this->right->child_count + 1;
				delete this->right;
			}
			this->right = right;
			if (right != NULL)
				child_count += right->child_count + 1;
		}
		inline T getValue() const
				{ return value; }
		inline size_t getChildCount() const
				{ return child_count; }
		inline BinaryTree<T> *getLeft()
				{ return left; }
		inline BinaryTree<T> *getRight()
				{ return right; }
		inline T getSum() const
		{
			T res = getValue();
			if (left != NULL)
				res += left->getSum();
			if (right != NULL)
				res += right->getSum();
			return res;
		}
		~BinaryTree()
		{
			if (left != NULL)
				delete left;
			if (right != NULL)
				delete right;
			child_count = 0;
		}
		static BinaryTree<T> *generate(size_t element_count, T min_value, T max_value)
		{
			if (element_count == 0)
				return NULL;
			T value = (T)ttg::math::getFloatRandom((float)min_value, (float)max_value);
			BinaryTree<T> *res = new BinaryTree<T>(value);
			if (element_count > 1)
			{
				int l_count = ttg::math::getIntRandom<int>(1, (int)element_count - 1);
				res->attachLeft(generate(l_count, min_value, max_value));
				res->attachRight(generate(element_count - 1 - l_count, min_value, max_value));
			}
			return res;
		};
};

#endif
